package com.jungle.client.control;

import com.jungle.client.utils.TableViewUtil;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableView;
import javafx.scene.control.ToolBar;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import lombok.extern.slf4j.Slf4j;
import org.kordamp.ikonli.javafx.FontIcon;

import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;

@Slf4j
public abstract class TableWithToolbar<T> implements Initializable {
    private List<Button> buttons;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        log.info("init TableWithToolbar, url:{}", url);
    }

    public VBox buildVBox(URL fxmlUrl, String title, TableButton... tableButtons) {
        VBox vBox = new VBox();
        vBox.getChildren().addAll(buildToolBar(title, tableButtons));
        buildTable(fxmlUrl, vBox);
        return vBox;
    }

    private ToolBar buildToolBar(String title, TableButton... tableButtons) {
        ToolBar toolBar = new ToolBar();
        Label titleLabel = new Label(title);
        toolBar.getItems().add(titleLabel);

        Region region = new Region();
        HBox.setHgrow(region, Priority.ALWAYS);
        toolBar.getItems().add(region);
        buttons = Arrays.stream(tableButtons).map(tableButton -> {
            Button button = new Button();
            button.setGraphic(new FontIcon(tableButton.iconCode()));
            button.setUserData(tableButton.disableIndex());
            button.setOnAction(getAction(tableButton));
            return button;
        }).toList();

        toolBar.getItems().addAll(buttons);

        return toolBar;
    }

    private void buildTable(URL fxmlUrl, VBox vBox) {
        try {
            // 使用FXMLLoader加载指定的FXML资源
            FXMLLoader fxmlLoader = new FXMLLoader(fxmlUrl);
            // 设置资源捆绑，用于国际化
            fxmlLoader.setResources(com.jungle.client.FxApplication.bundle);
            TableView<T> tableView = fxmlLoader.load();
            // 给TableView绑定双击事件
            tableView.setOnMouseClicked(this::onMouseClicked);
            // 给TableView添加选中监听
            tableView.getSelectionModel().selectedIndexProperty().addListener((observable, oldValue, rowIndex) -> {
                log.info("selected:{}", rowIndex);
                buttons.forEach(button -> {
                    if (button.getUserData() instanceof Integer index) {
                        if (index == Integer.MAX_VALUE) {
                            index = tableView.getItems().size() - 1;
                        }
                        button.setDisable(rowIndex.intValue() == index);
                    }
                });
            });
            // 将TableView添加到VBox中
            vBox.getChildren().add(tableView);
            //TableWithToolbar<T> controller = fxmlLoader.getController();
        } catch (IOException e) {
            log.error("loadFxml error, url:{}", fxmlUrl, e);
        }
    }

    private EventHandler<ActionEvent> getAction(TableButton tableButton) {
        return switch (tableButton) {
            case ADD -> this::doAdd;
            case EDIT -> this::doEdit;
            case DELETE -> this::doDelete;
            case REFRESH -> this::doRefresh;
            case MOVE_UP -> this::doMoveUp;
            case MOVE_DOWN -> this::doMoveDown;
        };
    }

    protected abstract TableView<T> getTableView();

    private void doMoveDown(ActionEvent actionEvent) {
        log.info("doMoveDown:{}", actionEvent);
        TableView<T> tableView = getTableView();
        int selectedIndex = tableView.getSelectionModel().getSelectedIndex();
        if (selectedIndex < tableView.getItems().size() - 1 && selectedIndex >= 0) {
            // 交换选中行和下一行的数据
            T selectedPerson = tableView.getItems().get(selectedIndex);
            T nextPerson = tableView.getItems().get(selectedIndex + 1);
            tableView.getItems().set(selectedIndex + 1, selectedPerson);
            tableView.getItems().set(selectedIndex, nextPerson);
            // 重新选中移动后的行
            tableView.getSelectionModel().select(selectedIndex + 1);
        }
    }

    private void doMoveUp(ActionEvent actionEvent) {
        log.info("doMoveUp:{}", actionEvent);
        TableView<T> tableView = getTableView();
        int selectedIndex = tableView.getSelectionModel().getSelectedIndex();
        if (selectedIndex > 0) {
            // 交换选中行和上一行的数据
            T selectedPerson = tableView.getItems().get(selectedIndex);
            T previousPerson = tableView.getItems().get(selectedIndex - 1);
            tableView.getItems().set(selectedIndex - 1, selectedPerson);
            tableView.getItems().set(selectedIndex, previousPerson);
            // 重新选中移动后的行
            tableView.getSelectionModel().select(selectedIndex - 1);
        }
    }

    protected void doDelete(ActionEvent actionEvent) {
        log.info("doDelete:{}", actionEvent);
    }

    protected void doEdit(ActionEvent actionEvent) {
        log.info("doEdit:{}", actionEvent);
    }

    protected void doAdd(ActionEvent actionEvent) {
        log.info("doAdd:{}", actionEvent);
    }

    protected void doRefresh(ActionEvent actionEvent) {
        log.info("doRefresh:{}", actionEvent);
    }

    private void onMouseClicked(MouseEvent mouseEvent) {
        if (mouseEvent.getClickCount() == 2) {
            log.info("onMouseClicked:{}", mouseEvent);
            TableViewUtil.traceTableRow(mouseEvent, tableRow -> {
                if (tableRow.isEmpty()) {
                    T selectedDataset = getTableView().getSelectionModel().getSelectedItem();
                    // add
                } else {
                    // edit
                }
            });
        }
    }
}
